home *** CD-ROM | disk | FTP | other *** search
/ Programming Windows 95 with MFC / Programming Windows 95 with MFC (Microsoft Programming Series)(097-0001465)(1996).iso / NT / CODE / CHAP03 / TICTAC / TICTAC.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-05  |  5.9 KB  |  258 lines

  1. //***********************************************************************
  2. //
  3. //  TicTac.cpp
  4. //
  5. //***********************************************************************
  6.  
  7. #include <afxwin.h>
  8. #include "Resource.h"
  9. #include "TicTac.h"
  10.  
  11. #define EX 1
  12. #define OH 2
  13.  
  14. CMyApp myApp;
  15.  
  16. /////////////////////////////////////////////////////////////////////////
  17. // CMyApp member functions
  18.  
  19. BOOL CMyApp::InitInstance ()
  20. {
  21.     m_pMainWnd = new CMainWindow;
  22.     m_pMainWnd->ShowWindow (m_nCmdShow);
  23.     m_pMainWnd->UpdateWindow ();
  24.     return TRUE;
  25. }
  26.  
  27. /////////////////////////////////////////////////////////////////////////
  28. // CMainWindow message map and member functions
  29.  
  30. BEGIN_MESSAGE_MAP (CMainWindow, CWnd)
  31.     ON_WM_PAINT ()
  32.     ON_WM_LBUTTONDOWN ()
  33.     ON_WM_LBUTTONDBLCLK ()
  34.     ON_WM_RBUTTONDOWN ()
  35. END_MESSAGE_MAP ()
  36.  
  37. const CRect CMainWindow::m_rcSquares[9] = {
  38.     CRect ( 16,  16, 112, 112),
  39.     CRect (128,  16, 224, 112),
  40.     CRect (240,  16, 336, 112),
  41.     CRect ( 16, 128, 112, 224),
  42.     CRect (128, 128, 224, 224),
  43.     CRect (240, 128, 336, 224),
  44.     CRect ( 16, 240, 112, 336),
  45.     CRect (128, 240, 224, 336),
  46.     CRect (240, 240, 336, 336)
  47. };
  48.  
  49. CMainWindow::CMainWindow ()
  50. {
  51.     m_nNextChar = EX;
  52.     ::ZeroMemory (m_nGameGrid, 9 * sizeof (int));
  53.  
  54.     CString strWndClass = AfxRegisterWndClass (
  55.         CS_DBLCLKS,                             // Class style
  56.         myApp.LoadStandardCursor (IDC_ARROW),   // Class cursor
  57.         (HBRUSH) (COLOR_3DFACE + 1),            // Class background brush
  58.         myApp.LoadIcon (IDI_APPICON)            // Class icon
  59.     );
  60.  
  61.     CreateEx (0, strWndClass, "Tic-Tac-Toe",
  62.         WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX,
  63.         CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
  64.         NULL, NULL);
  65.  
  66.     CRect rect (0, 0, 352, 352);
  67.     CalcWindowRect (&rect);
  68.  
  69.     SetWindowPos (NULL, 0, 0, rect.Width (), rect.Height (),
  70.         SWP_NOZORDER | SWP_NOMOVE | SWP_NOREDRAW);
  71. }
  72.  
  73. void CMainWindow::PostNcDestroy ()
  74. {
  75.     delete this;
  76. }
  77.  
  78. void CMainWindow::OnPaint ()
  79. {
  80.     CPaintDC dc (this);
  81.     DrawBoard (&dc);    
  82. }
  83.  
  84. void CMainWindow::OnLButtonDown (UINT nFlags, CPoint point)
  85. {
  86.     if (m_nNextChar != EX)
  87.         return;
  88.  
  89.     int nPos = GetRectID (point);
  90.     if (nPos == -1)
  91.         return;
  92.         
  93.     if (m_nGameGrid[nPos] != 0)
  94.         return;
  95.  
  96.     m_nNextChar = OH;
  97.     m_nGameGrid[nPos] = EX;
  98.  
  99.     CClientDC dc (this);
  100.     DrawX (&dc, nPos);
  101.  
  102.     CheckForGameOver ();
  103. }
  104.  
  105. void CMainWindow::OnRButtonDown (UINT nFlags, CPoint point)
  106. {
  107.     if (m_nNextChar != OH)
  108.         return;
  109.  
  110.     int nPos = GetRectID (point);
  111.     if (nPos == -1)
  112.         return;
  113.         
  114.     if (m_nGameGrid[nPos] != 0)
  115.         return;
  116.  
  117.     m_nNextChar = EX;
  118.     m_nGameGrid[nPos] = OH;
  119.  
  120.     CClientDC dc (this);
  121.     DrawO (&dc, nPos);
  122.  
  123.     CheckForGameOver ();
  124. }
  125.  
  126. void CMainWindow::OnLButtonDblClk (UINT nFlags, CPoint point)
  127. {
  128.     CClientDC dc (this);
  129.     if (dc.GetPixel (point) == RGB (0, 0, 0))
  130.         ResetGame ();
  131. }
  132.  
  133. int CMainWindow::GetRectID (CPoint point)
  134. {
  135.     for (int i=0; i<9; i++) {
  136.         if (m_rcSquares[i].PtInRect (point))
  137.             return i;
  138.     }
  139.     return -1;
  140. }
  141.  
  142. void CMainWindow::DrawBoard (CDC* pDC)
  143. {
  144.     CPen pen (PS_SOLID, 16, RGB (0, 0, 0));
  145.     CPen* pOldPen = pDC->SelectObject (&pen);
  146.  
  147.     pDC->MoveTo (120, 16);
  148.     pDC->LineTo (120, 336);
  149.  
  150.     pDC->MoveTo (232, 16);
  151.     pDC->LineTo (232, 336);
  152.  
  153.     pDC->MoveTo (16, 120);
  154.     pDC->LineTo (336, 120);
  155.  
  156.     pDC->MoveTo (16, 232);
  157.     pDC->LineTo (336, 232);
  158.  
  159.     for (int i=0; i<9; i++) {
  160.         if (m_nGameGrid[i] == EX)
  161.             DrawX (pDC, i);
  162.         else if (m_nGameGrid[i] == OH)
  163.             DrawO (pDC, i);
  164.     }
  165.     pDC->SelectObject (pOldPen);
  166. }
  167.  
  168. void CMainWindow::DrawX (CDC* pDC, int nPos)
  169. {
  170.     CPen pen (PS_SOLID, 16, RGB (255, 0, 0));
  171.     CPen* pOldPen = pDC->SelectObject (&pen);
  172.  
  173.     pDC->MoveTo (m_rcSquares[nPos].left + 16,
  174.         m_rcSquares[nPos].top + 16);
  175.     pDC->LineTo (m_rcSquares[nPos].right - 16,
  176.         m_rcSquares[nPos].bottom - 16);
  177.  
  178.     pDC->MoveTo (m_rcSquares[nPos].left + 16,
  179.         m_rcSquares[nPos].bottom - 16);
  180.     pDC->LineTo (m_rcSquares[nPos].right - 16,
  181.         m_rcSquares[nPos].top + 16);
  182.  
  183.     pDC->SelectObject (pOldPen);
  184. }
  185.  
  186. void CMainWindow::DrawO (CDC* pDC, int nPos)
  187. {
  188.     CPen pen (PS_SOLID, 16, RGB (0, 0, 255));
  189.     CPen* pOldPen = pDC->SelectObject (&pen);
  190.     pDC->SelectStockObject (NULL_BRUSH);
  191.  
  192.     CRect rect = m_rcSquares[nPos];
  193.     rect.DeflateRect (16, 16);
  194.     pDC->Ellipse (rect);
  195.  
  196.     pDC->SelectObject (pOldPen);
  197. }
  198.  
  199. void CMainWindow::CheckForGameOver ()
  200. {
  201.     int nWinner;
  202.  
  203.     if (nWinner = IsWinner ()) {
  204.         CString string = (nWinner == EX) ?
  205.             "The X's win!" : "The O's win!";
  206.         MessageBox (string, "Game Over", MB_ICONEXCLAMATION | MB_OK);
  207.         ResetGame ();
  208.     }
  209.     else if (IsDraw ()) {
  210.         MessageBox ("It's a draw!", "Game Over",
  211.             MB_ICONEXCLAMATION | MB_OK);
  212.         ResetGame ();
  213.     }
  214. }
  215.  
  216. int CMainWindow::IsWinner ()
  217. {
  218.     static int nPattern[8][3] = {
  219.         0, 1, 2,
  220.         3, 4, 5,
  221.         6, 7, 8,
  222.         0, 3, 6,
  223.         1, 4, 7,
  224.         2, 5, 8,
  225.         0, 4, 8,
  226.         2, 4, 6
  227.     };
  228.  
  229.     for (int i=0; i<8; i++) {
  230.         if ((m_nGameGrid[nPattern[i][0]] == EX) &&
  231.             (m_nGameGrid[nPattern[i][1]] == EX) &&
  232.             (m_nGameGrid[nPattern[i][2]] == EX))
  233.             return EX;
  234.  
  235.         if ((m_nGameGrid[nPattern[i][0]] == OH) &&
  236.             (m_nGameGrid[nPattern[i][1]] == OH) &&
  237.             (m_nGameGrid[nPattern[i][2]] == OH))
  238.             return OH;
  239.     }
  240.     return 0;
  241. }
  242.  
  243. BOOL CMainWindow::IsDraw ()
  244. {
  245.     for (int i=0; i<9; i++) {
  246.         if (m_nGameGrid[i] == 0)
  247.             return FALSE;
  248.     }
  249.     return TRUE;
  250. }
  251.  
  252. void CMainWindow::ResetGame ()
  253. {
  254.     m_nNextChar = EX;
  255.     ::ZeroMemory (m_nGameGrid, 9 * sizeof (int));
  256.     Invalidate ();
  257. }
  258.